package mrpanyu.guitool.yunduan;

import java.io.File;
import java.io.FileOutputStream;
import java.util.Base64;
import java.util.concurrent.atomic.AtomicBoolean;

import mrpanyu.guitool.base.annotation.Action;
import mrpanyu.guitool.base.annotation.Parameter;
import mrpanyu.guitool.base.annotation.ToolModel;
import mrpanyu.guitool.base.model.ParameterType;
import mrpanyu.guitool.base.model.Tool;
import mrpanyu.guitool.base.util.CommonUtils;

@ToolModel(displayName = "云端导入-VM端", description = "使用云端VM内可以读取Host机剪贴板文本的功能，传输文件。这个在VM端执行，接收文件")
public class YunduanImportVM {

	@Parameter(displayName = "输出文件", type = ParameterType.FILE, order = 1)
	private File outputFile;

	@Parameter(displayName = "监听间隔毫秒", description = "读取剪贴板内容的间隔毫秒数，数值小失败率低，但CPU消耗增高", order = 2)
	private String listenDelayStr = "50";

	private AtomicBoolean stopFlag = new AtomicBoolean(false);

	@Action(displayName = "启动监听", order = 1)
	public void startListen(Tool tool) throws Exception {
		tool.clearMessages();
		stopFlag.set(false);
		long listenDelay = Long.parseLong(listenDelayStr);
		long nextPieceNo = 1;
		String text = getClipboardText();
		FileOutputStream fout = null;
		try {
			if ("<ready-0>".equals(text)) {
				fout = new FileOutputStream(outputFile);
				nextPieceNo = 1;
				tool.infoMessage("已开始监听，传输方式为新文件传输，可在Host端开始传输");
			} else if (text.startsWith("<ready-")) {
				fout = new FileOutputStream(outputFile, true);
				String no = text.substring(7, text.length() - 1);
				nextPieceNo = Long.parseLong(no) + 1;
				tool.infoMessage("已开始监听，传输方式为从分片" + nextPieceNo + "开始续传，可在Host端开始传输");
			} else {
				tool.errorMessage("请先在Host端准备传输，然后再启动VM端监听");
				return;
			}
			while (true) {
				Thread.sleep(listenDelay);
				if (stopFlag.get()) {
					break;
				}
				text = getClipboardText();
				if (text == null) {
					continue;
				} else if (text.startsWith("<p-")) {
					int idx = text.indexOf('>');
					String no = text.substring(3, idx);
					long pieceNo = Long.parseLong(no);
					if (pieceNo == nextPieceNo) {
						String base64 = text.substring(idx + 1);
						byte[] data = Base64.getDecoder().decode(base64);
						fout.write(data);
						nextPieceNo++;
						tool.infoMessage("分片" + pieceNo + "传输完成");
					} else if (pieceNo > nextPieceNo) {
						tool.errorMessage("缺失分片" + nextPieceNo + "，传输未完成");
						break;
					}
				} else if ("<stopped>".equals(text)) {
					tool.errorMessage("Host端停止传输，传输未完成");
					break;
				} else if ("<done>".equals(text)) {
					tool.infoMessage("Host端结束传输，传输完成");
					break;
				}
			}
			tool.infoMessage("监听已停止");
		} finally {
			if (fout != null) {
				fout.close();
			}
		}
	}

	@Action(displayName = "停止监听", order = 2)
	public void stopListen(Tool tool) throws Exception {
		stopFlag.set(true);
	}

	private String getClipboardText() {
		RuntimeException ex = null;
		for (int i = 0; i < 3; i++) {
			try {
				return CommonUtils.getClipboardText();
			} catch (RuntimeException e) {
				ex = e;
			}
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// ignore
			}
		}
		throw ex;
	}

}
